package com.siyoumi.config;

import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.util.XStr;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;


public class CustomHttpServletRequestWrapper
        extends HttpServletRequestWrapper {
    /**
     * 缓存下来的HTTP body
     */
    private String body;
    private HttpServletRequest request;


    @SneakyThrows
    public CustomHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);

        this.request = request;
    }


    /**
     * 重新包装输入流
     */
    @SneakyThrows
    @Override
    public ServletInputStream getInputStream() {
        if (body == null) {
            body = getBodyString();
        }

        InputStream bodyStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bodyStream.read();
            }

            /**
             * 下面的方法一般情况下不会被使用，如果你引入了一些需要使用ServletInputStream的外部组件，可以重点关注一下。
             *
             * @return
             */
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    @SneakyThrows
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }


    @SneakyThrows
    private String getBodyString() {
        HttpServletRequest request = this.request;
        String contentType = request.getContentType();

        String bodyString = "";
        if (XStr.hasAnyText(contentType)
                && (contentType.contains("multipart/form-data")
                || contentType.contains("x-www-form-urlencoded"))) {
            StringBuilder sb = new StringBuilder();
            //
            Map<String, String[]> parameterMap = request.getParameterMap();
            for (Map.Entry<String, String[]> next : parameterMap.entrySet()) {
                String[] values = next.getValue();
                String value = null;
                if (values != null) {
                    if (values.length == 1) {
                        value = values[0];
                    } else {
                        value = Arrays.toString(values);
                    }
                }
                sb.append(next.getKey()).append("=").append(value).append("&");
            }
            if (sb.length() > 0) {
                bodyString = sb.substring(0, sb.toString().length() - 1);
            }
        } else {
            byte[] bodyByte = StreamUtils.copyToByteArray(request.getInputStream());
            bodyString = new String(bodyByte);
        }

        return bodyString;
    }
}
